﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Reflection;
using System.Text;
using VitCode.Castle.Entities;
using VitCode.Castle.Helper;

namespace AMS.History.Entities
{
    /// <summary>
    /// 历史记录基类
    /// </summary>
    public abstract class BaseHistoryEntity
    {
        private ObjectBuildHelper objBuilderHlp = new ObjectBuildHelper();

        public static string CREATE_HIS_RECORD = "CreateHisRecord";
        public static string HIS_OBJ_LAST_NAME = "Record";
        public static string H_BASE_OBJECT_ID = "HBaseObjectId";
        public static string H_ID = "HId";
        public static string H_PARENT_ID = "HParentId";
        public static string H_IS_LAST = "HIsLast";
        public static string H_MEMO = "HMemo";
        public static string H_VERSION_ID = "HVersionId";
        public static string GET_HISTORY_OBJECT_TYPE = "GetHistoryObjectType";
        public static string ASSEMBLY_NAME = "AMS.History", TYPE_NAME_SPACE = "AMS.History.Entities";
                        

        //public static StringCollection NOT_COMPARE_PRO_NAMES = new StringCollection() {H_BASE_OBJECT_ID,H_ID,H_IS_LAST,H_MEMO,H_PARENT_ID,H_VERSION_ID};

        //public StringCollection

        protected Guid m_HId;
        /// <summary>
        /// 数据唯一标识
        /// </summary>
        public virtual Guid HId
        {
            get { return m_HId; }
            set { m_HId = value; }
        }

        protected int m_HVersionId;
        /// <summary>
        /// 版本ID号,这里用Int型能更加明确版本产生的先后
        /// </summary>
        public virtual int HVersionId
        {
            get { return m_HVersionId; }
            set { m_HVersionId = value; }
        }

        protected Guid m_HParentId;
        /// <summary>
        /// 上一版本历史记录ID
        /// </summary>
        public virtual Guid HParentId
        {
            get { return m_HParentId; }
            set { m_HParentId = value; }
        }

        protected bool m_HIsLast;
        /// <summary>
        /// 是否最新
        /// </summary>
        public virtual bool HIsLast
        {
            get { return m_HIsLast; }
            set { m_HIsLast = value; }
        }

        protected Guid m_HBaseObjectId;
        /// <summary>
        /// 记录对应的主体对象ID
        /// </summary>
        public virtual Guid HBaseObjectId
        {
            get { return m_HBaseObjectId; }
            set { m_HBaseObjectId = value; }
        }

        protected string m_HisMemo;
        /// <summary>
        /// 历史备注(历史记录级)
        /// </summary>
        public virtual string HisMemo
        {
            get { return m_HisMemo; }
            set { m_HisMemo = value; }
        }

        protected string m_Memo;
        /// <summary>
        /// 备注
        /// </summary>
        public virtual string Memo
        {
            get { return m_Memo; }
            set { m_Memo = value; }
        }

        protected bool m_IsLogicDelete;
        /// <summary>
        /// 逻辑删除的标记
        /// </summary>
        public virtual bool IsLogicDelete
        {
            get { return m_IsLogicDelete; }
            set { m_IsLogicDelete = value; }
        }

        protected string m_KeyWord;
        /// <summary>
        /// 关键字(以","分格)
        /// </summary>
        public virtual string KeyWord
        {
            get { return m_KeyWord; }
            set { m_KeyWord = value; }
        }

        

        public static StringCollection GetNotCompareProNames(object obj)
        {
            StringCollection scNotCompareProNames = new StringCollection();
            MethodInfo m = obj.GetType().GetMethod("GetNotCompareHisProNames");
            if (m != null)
            {
                object moResultVal = m.Invoke(obj, null);
                if (moResultVal != null)
                    scNotCompareProNames = (StringCollection)moResultVal;
            }
            return scNotCompareProNames;
        }

        public static bool CompareToBaseHisObject(object obj, object hisObj,HisVersionInfo hisVerInfo)
        {
            if (obj == null)
                throw new ArgumentException("记录历史的对象不能为空");
            if (hisVerInfo == null)
                throw new ArgumentException("历史版本对象不能为空");
            if (hisVerInfo.WoInfoId != Guid.Empty)
                return false;
            PropertyInfo[] ps = obj.GetType().GetProperties();
            StringCollection scNotCompareProNames = GetNotCompareProNames(obj);
            if (ps != null)
            {
                foreach (PropertyInfo p in ps)
                {
                    if (scNotCompareProNames.Contains(p.Name))
                        continue;
                    PropertyInfo hisPro = hisObj.GetType().GetProperty(p.Name);
                    if (hisPro != null)//找得到存在与主对象一样的属性
                    {
                        object hisProVal = hisPro.GetValue(hisObj, null);
                        object proVal = p.GetValue(obj, null);

                        if ((hisProVal == null && proVal != null) || (hisProVal != null && proVal == null))
                            return false;
                        if (hisProVal != null && proVal != null && !hisProVal.Equals(proVal))
                            return false;
                    }
                    else
                    {
                        string strMayBeHisPro = p.Name + "Id";//找一下是不是在历史表中只记录了ID,在主表中记录的是
                        hisPro = hisObj.GetType().GetProperty(strMayBeHisPro);
                        if (hisPro != null)
                        {
                            object hisProVal = hisPro.GetValue(hisObj, null);
                            object proObj = p.GetValue(obj, null);
                            if (proObj != null)
                            {
                                PropertyInfo proObjId = proObj.GetType().GetProperty("Id");
                                if (proObjId != null)
                                {
                                    if (!proObjId.PropertyType.Equals(hisProVal.GetType()))
                                        throw new ArgumentException("主体对象的子对象属性Id与历史表中的Id属性类型不一致");
                                    object proObjIdVal = proObjId.GetValue(proObj, null);
                                    if (((proObjIdVal == null && hisProVal != null)||(proObjIdVal != null && hisProVal == null)) || 
                                        (proObjIdVal!=null&&hisProVal!=null) && !proObjIdVal.Equals(hisProVal))
                                        return false;
                                }
                            }
                        }
                    }
                }
            }
            return true;
        }

        public virtual void CreateHisRecord(object obj,int versionId,string hisMemo)
        {
            if (obj == null)
                new ArgumentException("主体对象不能为空,否则无法创建历史对象");
            PropertyInfo[] ps = obj.GetType().GetProperties();
            if (ps.Length==0)
            {
                return;
            }
            StringCollection scNotCompareProNames = GetNotCompareProNames(obj);
            foreach (PropertyInfo p in ps)
            {
                if (scNotCompareProNames.Contains(p.Name))
                    continue;
                PropertyInfo hisP = GetType().GetProperty(p.Name);
                if (hisP != null)
                {
                    object objProVal = p.GetValue(obj, null);
                    hisP.SetValue(this,objProVal , null);
                }
                else
                {
                    string mayBeHisProName = p.Name + BaseEntity.ID;
                    hisP = GetType().GetProperty(mayBeHisProName);
                    object proChildObj = p.GetValue(obj, null);
                    if (proChildObj == null)
                        continue;
                    PropertyInfo proChildObjId = proChildObj.GetType().GetProperty(BaseEntity.ID);
                    if (proChildObjId == null || !proChildObjId.PropertyType.Equals(hisP.PropertyType))
                        continue;
                    object valChildObjId = proChildObjId.GetValue(proChildObj, null);
                    hisP.SetValue(this, valChildObjId, null);
                }
            }

            object objBaseObjectId = objBuilderHlp.GetPropertyValue(BaseEntity.ID, obj);
            m_HBaseObjectId = (Guid)objBaseObjectId;
            m_HVersionId = versionId;
            m_HIsLast = true;
        }
    }
}
